﻿using System;
using System.Collections.Generic;
using Autodesk.Revit.DB;
using YJKCodeBase.Math;
using YJKRevitCode.XYZUtility;

namespace YJKRevitCode.CurveUtility
{
	public static class CurveUtilityMethod
	{
		public static Curve GetUnBoundCurve(Curve input)
		{
			if (null == input || !input.IsBound)
			{
				return input;
			}
			Curve curve = input.Clone();
			curve.MakeUnbound();
			return curve;
		}

		public static bool IfPointOnCurve(Curve inputCurve, XYZ inputPoint, bool ifBound = true)
		{
			if (null == inputCurve || inputPoint == null)
			{
				return false;
			}
			Curve curve = inputCurve.Clone();
			if (curve.IsBound)
			{
				curve.MakeUnbound();
			}
			XYZ xyzpoint = inputCurve.Project(inputPoint).XYZPoint;
			XYZ xyzpoint2 = curve.Project(inputPoint).XYZPoint;
			return inputPoint.IsAlmostEqualTo(xyzpoint, MathUtility.GetPrecision(3)) && inputPoint.IsAlmostEqualTo(xyzpoint2, MathUtility.GetPrecision(3));
		}

		public static bool IfTwoBoundLineIsSameLine(Line inputOne, Line inputTwo)
		{
			return XYZUtilityMethod.Is_Points_Collinear(inputOne.GetEndPoint(0), inputOne.GetEndPoint(1), inputTwo.GetEndPoint(0), 1E-09) && XYZUtilityMethod.Is_Points_Collinear(inputOne.GetEndPoint(0), inputOne.GetEndPoint(1), inputTwo.GetEndPoint(1), 1E-09);
		}

		public static bool TryGetIntersectionPoint(Curve inputCurveOne, Curve inputCurveTwo, out XYZ interectionPoint)
		{
			interectionPoint = null;
			IntersectionResultArray intersectionResultArray = null;
			bool result;
			try
			{
				SetComparisonResult setComparisonResult = inputCurveOne.Intersect(inputCurveTwo, out intersectionResultArray);
				if (setComparisonResult == SetComparisonResult.Overlap)
				{
                    interectionPoint = intersectionResultArray.get_Item(0).XYZPoint;
					result = true;
				}
				else
				{
					result = false;
				}
			}
			catch (Exception)
			{
				result = false;
			}
			return result;
		}

		public static List<Curve> SplitOneCurve(Curve inputCurve, double useLength)
		{
			List<Curve> list = new List<Curve>();
			if (!inputCurve.IsBound)
			{
				return list;
			}
			double endParameter = inputCurve.GetEndParameter(0);
			double endParameter2 = inputCurve.GetEndParameter(1);
			double num = 0.0;
			double length = inputCurve.Length;
			num = endParameter;
			double num2 = (endParameter2 - endParameter) * useLength / length;
			while (MathUtility.Lessthan_Or_Equal(num + num2, endParameter2))
			{
				Curve curve = inputCurve.Clone();
				try
				{
					curve.MakeBound(num, num + num2);
					list.Add(curve);
				}
				catch
				{
				}
				num += num2;
			}
			if (MathUtility.Lessthan_Or_Equal(num, endParameter2))
			{
				Curve curve = inputCurve.Clone();
				try
				{
					curve.MakeBound(num, endParameter2);
					list.Add(curve);
				}
				catch
				{
				}
			}
			return list;
		}

		public static Curve TransformCurveAtZAixs(Curve inputCurve, double moveZValue, bool ifAbsolute = true)
		{
			XYZ endPoint = inputCurve.GetEndPoint(0);
			XYZ xyz;
			if (!ifAbsolute)
			{
				xyz = new XYZ(endPoint.X, endPoint.Y, endPoint.Z + moveZValue);
			}
			else
			{
				xyz = new XYZ(endPoint.X, endPoint.Y, moveZValue);
			}
			Transform transform = Transform.CreateTranslation(xyz.Add(-endPoint));
			Curve curve = inputCurve.Clone();
			return curve.CreateTransformed(transform);
		}

		public static Line AdjustLineToNearPoint(Line input, XYZ inputPoint)
		{
			XYZ endPoint = input.GetEndPoint(0);
			XYZ endPoint2 = input.GetEndPoint(1);
			XYZ xyz = endPoint;
			bool flag = true;
			if (MathUtility.GreaterThan(endPoint2.DistanceTo(inputPoint), endPoint.DistanceTo(inputPoint)))
			{
				xyz = endPoint2;
				flag = false;
			}
			if (flag)
			{
				return Line.CreateBound(xyz, inputPoint);
			}
			return Line.CreateBound(inputPoint, xyz);
		}

		public static Curve CreateOffsetCurve(Curve curve, double dOffsetDist)
		{
			Line line = curve as Line;
			if (line != null)
			{
				XYZ direction = line.Direction;
				XYZ xyz = direction.CrossProduct(XYZ.BasisZ);
				xyz = xyz.Normalize() * dOffsetDist;
				return Line.CreateBound(line.GetEndPoint(0) + xyz, line.GetEndPoint(1) + xyz);
			}
			Arc arc = curve as Arc;
			if (null != arc)
			{
				XYZ center = arc.Center;
				double radius = arc.Radius;
				double num = radius + dOffsetDist;
				XYZ xyz2 = arc.Evaluate(0.5, true);
				XYZ xyz3 = arc.GetEndPoint(0).Add(-center).Normalize();
				XYZ xyz4 = arc.GetEndPoint(1).Add(-center).Normalize();
				XYZ xyz5 = xyz2.Add(-center).Normalize();
				XYZ xyz6 = center.Add(xyz3.Multiply(num));
				XYZ xyz7 = center.Add(xyz4.Multiply(num));
				XYZ xyz8 = center.Add(xyz5.Multiply(num));
				return Arc.Create(xyz6, xyz7, xyz8);
			}
			throw new ArgumentException();
		}

		public static bool LineToString(Line line, out string lineString)
		{
			bool result;
			try
			{
				lineString = "Line:" + line.GetEndPoint(0).ToString() + ":" + line.GetEndPoint(1).ToString();
				result = true;
			}
			catch
			{
				lineString = string.Empty;
				result = false;
			}
			return result;
		}

		public static bool LineToString(List<Line> lstLine, out List<string> lstLineString)
		{
			lstLineString = new List<string>();
			bool result;
			try
			{
				string empty = string.Empty;
				foreach (Line line in lstLine)
				{
					CurveUtilityMethod.LineToString(line, out empty);
					lstLineString.Add(empty);
				}
				result = true;
			}
			catch
			{
				lstLineString = null;
				result = false;
			}
			return result;
		}
	}
}
